package com.mbigger.admin.service.impl;

import com.google.common.base.Preconditions;
import com.mbigger.admin.common.RequestHolder;
import com.mbigger.admin.dao.AclMapper;
import com.mbigger.admin.dao.AclModuleMapper;
import com.mbigger.admin.entity.AclModule;
import com.mbigger.admin.exception.ParamException;
import com.mbigger.admin.param.AclModuleParam;
import com.mbigger.admin.service.AclModuleService;
import com.mbigger.admin.util.BeanValidator;
import com.mbigger.admin.util.IpUtil;
import com.mbigger.admin.util.LevelUtil;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
public class AclModuleServiceImpl implements AclModuleService{

	@Autowired
	private AclModuleMapper aclModuleMapper;
	@Autowired
	private AclMapper aclMapper;

	public void save(AclModuleParam param) {
		BeanValidator.check(param);
		if (checkExist(param.getParentId(), param.getName(), param.getId())) {
			throw new ParamException("同一层级下存在相同名称的权限模块");
		}
		AclModule aclModule = AclModule.builder().name(param.getName()).parentId(param.getParentId())
				.seq(param.getSeq()).status(param.getStatus()).remark(param.getRemark()).build();
		aclModule.setLevel(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()));
		aclModule.setOperator(RequestHolder.getCurrentUser().getUsername());
		aclModule.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
		aclModule.setOperateTime(new Date());
		aclModuleMapper.insert(aclModule);
	}

	public void update(AclModuleParam param) {
		BeanValidator.check(param);
		if (checkExist(param.getParentId(), param.getName(), param.getId())) {
			throw new ParamException("同一层级下存在相同名称的权限模块");
		}
		AclModule before = aclModuleMapper.selectById(param.getId());
		Preconditions.checkNotNull(before, "待更新的权限模块不存在");

		AclModule after = AclModule.builder().id(param.getId()).name(param.getName()).parentId(param.getParentId())
				.seq(param.getSeq()).status(param.getStatus()).remark(param.getRemark()).build();
		after.setLevel(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()));
		after.setOperator(RequestHolder.getCurrentUser().getUsername());
		after.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
		after.setOperateTime(new Date());

		updateWithChild(before, after);
	}

	@Transactional // 如果要保证事务生效，需要调整这个方法，一个可行的方法是重新创建一个service类，然后把这个方法转移过去
	public void updateWithChild(AclModule before, AclModule after) {
		String newLevelPrefix = after.getLevel();
		String oldLevelPrefix = before.getLevel();
		if (!after.getLevel().equals(before.getLevel())) {
			String curLevel = before.getLevel() + "." + before.getId();
			List<AclModule> aclModuleList = aclModuleMapper.getChildAclModuleListByLevel(curLevel + "%");
			if (CollectionUtils.isNotEmpty(aclModuleList)) {
				for (AclModule aclModule : aclModuleList) {
					String level = aclModule.getLevel();
					if (level.equals(curLevel) || level.indexOf(curLevel + ".") == 0) {
						// getChildAclModuleListByLevel可能会取出多余的内容，因此需要加个判断
						// 比如0.1* 可能取出0.1、0.1.3、0.11、0.11.3，而期望取出 0.1、0.1.3， 因此呢需要判断等于0.1或者以0.1.为前缀才满足条件
						level = newLevelPrefix + level.substring(oldLevelPrefix.length());
						aclModule.setLevel(level);
					}
				}
				aclModuleMapper.batchUpdateLevel(aclModuleList);
			}
		}
		aclModuleMapper.updateById(after);
	}

	private boolean checkExist(Integer parentId, String aclModuleName, Integer deptId) {
		return aclModuleMapper.countByNameAndParentId(parentId, aclModuleName, deptId) > 0;
	}

	private String getLevel(Integer aclModuleId) {
		AclModule aclModule = aclModuleMapper.selectById(aclModuleId);
		if (aclModule == null) {
			return null;
		}
		return aclModule.getLevel();
	}

	public void delete(int aclModuleId) {
		AclModule aclModule = aclModuleMapper.selectById(aclModuleId);
		Preconditions.checkNotNull(aclModule, "待删除的权限模块不存在，无法删除");
		if (aclModuleMapper.countByParentId(aclModule.getId()) > 0) {
			throw new ParamException("当前模块下面有子模块，无法删除");
		}
		if (aclMapper.countByAclModuleId(aclModule.getId()) > 0) {
			throw new ParamException("当前模块下面有用户，无法删除");
		}
		aclModuleMapper.deleteById(aclModuleId);
	}

}
